package com.thoughtworks.oo.quantity;

import static com.thoughtworks.oo.quantity.Delimiter.UNIT_DELIMITER;

class AllUnitsFormatter implements Formatter {
    public String format(int amount, LengthUnit unit) {
        return new FormatterImplementer(unit.getBaseAmount(amount)).format();
    }

    static class FormatterImplementer implements UnitVisitor {
        private int baseAmount;
        private int restAmount;
        private Delimiter delimiter;
        private StringBuffer result;

        FormatterImplementer(int baseAmount) {
            this.baseAmount = restAmount = baseAmount;
            delimiter = new Delimiter();
            result = new StringBuffer();
        }

        public String format() {
            LengthUnit.visitAllUnits(this);
            return result.toString();
        }

        @Override
        public boolean visit(LengthUnit unit) {
            return baseAmount == 0 ? formatZeroLength(unit) : formatNonZeroLength(unit);
        }

        private boolean formatZeroLength(LengthUnit unit) {
            formatUnit(0, (LengthUnit)unit.getBaseUnit(), result);
            return false;
        }

        private boolean formatNonZeroLength(LengthUnit unit) {
            int conversionFactor = unit.getBaseAmount(1);
            if (restAmount >= conversionFactor) {
                formatUnit(restAmount / conversionFactor, unit, result);
                restAmount %= conversionFactor;
            }
            return restAmount > 0;
        }

        private void formatUnit(int amount, LengthUnit unit, StringBuffer result) {
            result.append(delimiter).append(amount).append(UNIT_DELIMITER).append(unit);
        }

    }

}
